/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-30 17:16:56
 * @LastEditTime: 2021-09-09 18:34:29
 * @LastEditors: 0x9DEFA478
 * @Description: H_AudioResample负责双通道音频的重采样与音量调节 固定输入整型 输出整型 音量转换后的浮点可通过一个分支输出(例子:这个分支用于FFT源数据)
 *               当H_AudioResample内部样本过多或过少时进行重采样
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#ifndef __H_AudioResample_H_
#define __H_AudioResample_H_
#include "H_Type.h"


#define H_AudioResample_IntegerType                               Hint32
#define H_AudioResample_UnsignedIntegerType                       Huint32    //位宽必须与H_AudioResample_IntegerType相同
#define H_AudioResample_FloatType                                 float
#define cH_AudioResample_FloatConst(val)                          (val##f)


#define vH_AudioResample_ResampleCtrl_Status_SpeedDown             -1
#define vH_AudioResample_ResampleCtrl_Status_SpeedDefault          0
#define vH_AudioResample_ResampleCtrl_Status_SpeedUp               1

#define vH_AudioResample_Volume_ChannelMode_Stereo                 0  //立体声
#define vH_AudioResample_Volume_ChannelMode_ChannelL               1  //左声道
#define vH_AudioResample_Volume_ChannelMode_ChannelR               2  //右声道
#define vH_AudioResample_Volume_ChannelMode_ChannelSwap            3  //交换声道


typedef struct _H_AudioResample_ExtProcess{
  void* v;
  void (*Process)(void*,H_AudioResample_FloatType*,int);
  struct _H_AudioResample_ExtProcess* Next;
  struct _H_AudioResample_ExtProcess* Last;
}H_AudioResample_ExtProcess;

typedef struct _H_AudioResample{

  volatile int IsSuspend;//是否挂起 挂起时 as不工作 输出数据为NULL 不响应数据写入

  struct{

    volatile H_AudioResample_FloatType Channelx_AmplitudeMultiple[2];

    volatile int ChannelMode;
  }Volume;

  struct{
    int Status;//速度状态
    volatile int IsDefaultSpeed;//是否固定默认速度 若此段使能 将不进行速度校正

    H_AudioResample_FloatType SRC_Ratio;       //速率有偏差时附加的重采样倍数 为0~1之间的值
    int Threshold_SpeedDown;                   //输出缓冲区超过这个阈值时 减少输出样本的数量
    int Threshold_SpeedUpStop;                 //输出缓冲区超过这个阈值时 如果处于 增加输出样本 状态, 则恢复默认速度状态
    int Threshold_SpeedDownStop;               //输出缓冲区低于这个阈值时 如果处于 减少输出样本 状态, 则恢复默认速度状态
    int Threshold_SpeedUp;                     //输出缓冲区低于这个阈值时 增加输出样本的数量
  }ResampleCtrl;

  struct{
    H_AudioResample_FloatType* Buffer;
    volatile int SizeOfPerInput;//Buffer使用的的长度 单位:sizeof(H_AudioResample_FloatType)字节
    H_AudioResample_FloatType* volatile Buffer_WritePtr;//Buffer写指针
    volatile int LastInputLength;//Buffer剩余写入长度
  }Input;

  struct{
    H_AudioResample_IntegerType* Buffer;//输出缓冲区 要确保(OutputBufferBlockAllCount*SizeOfPerOutput)要小于OutputBuffer的大小
    int OutputBufferBlockAllCount;//缓冲块数量 多个缓存块连续分布在OutputBuffer
    int OutputBufferBlockMaxCount;//最大容纳数量
    volatile int SizeOfPerOutput;//每一次输出数据(即缓冲块)的长度 单位:sizeof(H_AudioResample_IntegerType)字节
    volatile int O;//BufferBlock读指针
    volatile int I;//BufferBlock写指针
    volatile int I_Block;//当前块的写指针 单位sizeof(H_AudioResample_IntegerType)字节
    volatile int OccupyCount;//输出缓存已填充数量
  }Output;

  H_AudioResample_FloatType LastData[8];

  H_AudioResample_ExtProcess* Process;//额外进程 参与音频处理

}H_AudioResample;









/**
 * @brief 获取音量倍数
 * @param Vol_i 0~100的音量值
 * @return noEdit
 */
H_AudioResample_FloatType H_AudioResample_GetMultiple(int Vol_i);

/**
 * @brief 初始化H_AudioResample
 * @param ar H_AudioResample对象
 * @param OutputBuffer 输出缓冲区 要确保(OutputBufferBlockAllCount*SizeOfPerOutput)要小于OutputBuffer的大小
 * @param OutputBufferBlockAllCount //缓冲块数量 多个缓存块连续分布在OutputBuffer
 * @param SizeOfPerOutput 每个输出包长度 需要保证这个为2的倍数 单位:sizeof(H_AudioResample_IntegerType)字节
 * @param InputBuffer 输入缓冲区 这个缓存负责将零碎的音频数据组成一个连续的数组 要确保SizeOfPerInput要小于InputBuffer的大小
 * @param SizeOfPerInput InputBuffer使用的长度 需要保证这个为2的倍数 单位:sizeof(H_AudioResample_FloatType)字节
 * @return 无
 */
void H_AudioResample_Init(H_AudioResample* ar
  ,H_AudioResample_IntegerType* OutputBuffer,int OutputBufferBlockAllCount,int SizeOfPerOutput
  ,H_AudioResample_FloatType* InputBuffer,int SizeOfPerInput);

/**
 * @brief 设置最容纳数量 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param OutputBufferBlockMaxCount 最大容纳数量 不能超过(OutputBufferBlockAllCount-1)
 * @return 无
 */
void H_AudioResample_SetOutputBufferBlockMaxCount(H_AudioResample* ar,int OutputBufferBlockMaxCount);

/**
 * @brief 设置重采样相关参数 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SRC_Ratio 速率有偏差时附加的重采样倍数 为0~1之间的值
 * @param Threshold_SpeedDown 输出缓冲区超过这个阈值时 减少输出样本的数量
 * @param Threshold_SpeedUpStop 输出缓冲区超过这个阈值时 如果处于 增加输出样本 状态, 则恢复默认速度状态
 * @param Threshold_SpeedDownStop 输出缓冲区低于这个阈值时 如果处于 减少输出样本 状态, 则恢复默认速度状态
 * @param Threshold_SpeedUp 输出缓冲区低于这个阈值时 增加输出样本的数量
 * @return 无
 */
void H_AudioResample_SetResample(H_AudioResample* ar,H_AudioResample_FloatType SRC_Ratio,int Threshold_SpeedDown,int Threshold_SpeedUpStop,int Threshold_SpeedDownStop,int Threshold_SpeedUp);

/**
 * @brief 设置输出包大小 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SizeOfPerOutput 每个输出包长度 单位:sizeof(H_AudioResample_IntegerType)字节
 * @return 无
 */
void H_AudioResample_SetSizeOfPerOutput(H_AudioResample* ar,int SizeOfPerOutput);

/**
 * @brief 设置输入缓存使用大小 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param SizeOfPerInput 每个输出包长度 单位:sizeof(H_AudioResample_FloatType)字节
 * @return 无
 */
void H_AudioResample_SetSizeOfPerInput(H_AudioResample* ar,int SizeOfPerInput);

/**
 * @brief 设置H_AudioResample状态
 * @param IsSuspend 0:正常工作 其他:挂起
 * @return 无
 */
void H_AudioResample_SetSuspend(H_AudioResample* ar,int IsSuspend);

/**
 * @brief 设置声道模式
 * @param ar H_AudioResample对象
 * @param ChannelMode 声道模式 vH_AudioResample_Volume_ChannelMode_Stereo
 *                            vH_AudioResample_Volume_ChannelMode_ChannelL
 *                            vH_AudioResample_Volume_ChannelMode_ChannelR
 *                            vH_AudioResample_Volume_ChannelMode_ChannelSwap
 * @return 无
 */
void H_AudioResample_SetChannelMode(H_AudioResample* ar,int ChannelMode);

/**
 * @brief 设置音量
 * @param ar H_AudioResample对象
 * @param MasterVolume 主音量
 * @param Volumes 各个声道音量
 * @return 无
 */
void H_AudioResample_SetVolume(H_AudioResample* ar,int MasterVolume,int* Volumes);

/**
 * @brief 设置音量倍数
 * @param ar H_AudioResample对象
 * @param MasterMultiple 主音量 (0~1)
 * @param VolumeMultiples 各个声道音量 (0~1)
 * @return 无
 */
void H_AudioResample_SetVolumeMultiple(H_AudioResample* ar,H_AudioResample_FloatType MasterMultiple,H_AudioResample_FloatType* VolumeMultiples);

/**
 * @brief 设置是否固定默认速度
 * @param ar H_AudioResample对象
 * @param IsDefaultSpeed 如果为0 则启用速度校正 否则不进行速度校正 原速输出
 * @return 无
 */
void H_AudioResample_SetIsDefaultSpeed(H_AudioResample* ar,int IsDefaultSpeed);




/**
 * @brief 初始化一个额外进程句柄
 * @param ExtProcess 要初始化的句柄对象
 * @param Process 进程回调
 * @param v Process调用时传入的参数
 * @return 无
 */
void H_AudioResample_ExtProcess_Init(H_AudioResample_ExtProcess* ExtProcess,void (*Process)(void*,H_AudioResample_FloatType*,int),void* v);

/**
 * @brief 添加进程到ar 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param refExtProcess 参考对象(该对象需在ar中) 添加到改对象的后一个 如果为NULL 则添加到头部
 * @param ExtProcess 要添加的进程对象
 * @return 无
 */
void H_AudioResample_AddExtProcess(H_AudioResample* ar,H_AudioResample_ExtProcess* refExtProcess,H_AudioResample_ExtProcess* ExtProcess);

/**
 * @brief 从ar中移除ExtProcess 在ar不工作(无数据输入和输出)时使用
 * @param ar H_AudioResample对象
 * @param ExtProcess 要移除的进程对象
 * @return 无
 */
void H_AudioResample_RemoveExtProcess(H_AudioResample* ar,H_AudioResample_ExtProcess* ExtProcess);











/**
 * @brief 获取可写入包数
 * @param ar H_AudioResample对象
 * @return 可写入包数
 */
int H_AudioResample_GetEmptyCount(H_AudioResample* ar);

/**
 * @brief 输出数据方法
 * @param ar H_AudioResample对象
 * @return 如果为NULL 表示目前无数据输出 否则为数据数据的指针
 */
H_AudioResample_IntegerType* H_AudioResample_Output(H_AudioResample* ar);

/**
 * @brief 向ar中写入数据
 * @param ar H_AudioResample对象
 * @param Buffer 数据缓存
 * @param Length 数据长度 要求为2的倍数 单位:sizeof(H_AudioResample_IntegerType)字节
 * @return 0:成功 其他:as已挂起或缓存满
 */
int H_AudioResample_Input(H_AudioResample* ar,H_AudioResample_IntegerType* Buffer,int Length);


#endif //__H_AudioResample_H_
